package com.contract.commonlib.view

import android.animation.ValueAnimator
import android.annotation.SuppressLint
import android.content.Context
import android.graphics.*
import android.util.AttributeSet
import android.view.View
import com.blankj.utilcode.util.ScreenUtils
import com.contract.commonlib.R

/**
 * @author: witness
 * created: 2021/10/22
 * desc:
 */
@SuppressLint("Recycle")
class ColorArcProgressBar : View {
    private var dotColor: Int = 0
    private var colors = intArrayOf(Color.GREEN, Color.YELLOW, Color.RED, Color.RED)
    private var startAngle = 160f
    private var sweepAngle = 270f
    private var bgArcWidth: Float = dipToPx(8f).toFloat()
    private var progressWidth: Float = dipToPx(10f).toFloat()
    private var dotWidth: Float = dipToPx(4f).toFloat()
    private var isNeedTitle: Boolean = false
    private var isNeedContent: Boolean = false
    private var isNeedDial: Boolean = false
    private var isNeedEndDot: Boolean = false
    private var isNeedUnit: Boolean = false
    private var hintString: String? = null
    private var titleString: String? = null
    private var maxValues = 60f
    private var curValues = 0f
    private var diameter: Float = 500f
    private var bgRect: RectF? = null
    private val longdegree = dipToPx(13f).toFloat()
    private var shortdegree = dipToPx(10f) //控制刻度的高度
        .toFloat()
    private val DEGREE_PROGRESS_DISTANCE = dipToPx(8f) //控制刻度距离圆弧的距离
    private var centerX //圆心X坐标
            = 0f
    private var centerY //圆心Y坐标
            = 0f

    // sweepAngle / maxValues 的值
    private var k = 0f
    private var lastAngle = 0f
    private var currentAngle = 0f
    private val aniSpeed = 1000

    constructor(context: Context) : this(context, null)
    constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
    constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(
        context,
        attrs,
        defStyleAttr
    ){
        initView()
        initConfig(context, attrs)
    }

    private fun initConfig(context: Context, attrs: AttributeSet?) {
        if(attrs==null){
            return
        }
        val typeArray = context.obtainStyledAttributes(attrs, R.styleable.ColorArcProgressBar)
        val color1 = typeArray.getColor(R.styleable.ColorArcProgressBar_front_color1, Color.GREEN)
        val color2: Int = typeArray.getColor(R.styleable.ColorArcProgressBar_front_color2, color1)
        val color3: Int = typeArray.getColor(R.styleable.ColorArcProgressBar_front_color3, color1)
        dotColor = typeArray.getColor(R.styleable.ColorArcProgressBar_dot_color, Color.GREEN)
        colors = intArrayOf(color1, color2, color3, color3)
        sweepAngle =
            typeArray.getInteger(R.styleable.ColorArcProgressBar_total_engle, 180).toFloat()
        bgArcWidth =
            typeArray.getDimension(
                R.styleable.ColorArcProgressBar_back_width,
                dipToPx(6f).toFloat()
            )
        dotWidth =
            typeArray.getDimension(R.styleable.ColorArcProgressBar_dot_width, dipToPx(5f).toFloat())
        progressWidth =
            typeArray.getDimension(
                R.styleable.ColorArcProgressBar_front_width,
                dipToPx(10f).toFloat()
            )
        isNeedTitle = typeArray.getBoolean(R.styleable.ColorArcProgressBar_is_need_title, false)
        isNeedContent = typeArray.getBoolean(R.styleable.ColorArcProgressBar_is_need_content, false)
        isNeedUnit = typeArray.getBoolean(R.styleable.ColorArcProgressBar_is_need_unit, false)
        isNeedDial = typeArray.getBoolean(R.styleable.ColorArcProgressBar_is_need_dial, false)
        isNeedEndDot = typeArray.getBoolean(R.styleable.ColorArcProgressBar_is_need_end_dot, false)
        hintString = typeArray.getString(R.styleable.ColorArcProgressBar_string_unit)
        titleString = typeArray.getString(R.styleable.ColorArcProgressBar_string_title)
        curValues = typeArray.getFloat(R.styleable.ColorArcProgressBar_current_value, 0f)
        maxValues = typeArray.getFloat(R.styleable.ColorArcProgressBar_max_value, 60f)
        diameter = typeArray.getDimension(R.styleable.ColorArcProgressBar_circleWidth, 0f)
        setCurrentValues(curValues)
        setMaxValues(maxValues)
        typeArray.recycle()
    }

    private lateinit var allArcPaint: Paint
    private lateinit var progressPaint: Paint
    private lateinit var vTextPaint: Paint
    private lateinit var hintPaint: Paint
    private lateinit var dotPaint: Paint
    private lateinit var degreePaint: Paint
    private lateinit var linePaint: Paint
    private lateinit var curSpeedPaint: Paint
    private val textSize = dipToPx(60f).toFloat()
    private val hintSize = dipToPx(15f).toFloat()
    private val curSpeedSize = dipToPx(25f).toFloat()
    private var mDrawFilter: PaintFlagsDrawFilter? = null
    private var sweepGradient: SweepGradient? = null
    private var rotateMatrix: Matrix? = null
    private val hintColor = "#575757"
    private val contentColor = "#3CCDB1"
    private val longDegreeColor = "#BCDEFF"
    private val shortDegreeColor = "#BCDEFF"
    private val bgArcColor = "#DEEEFF" //圆圈背景色（画笔颜色）

    private fun initView() {
        if (diameter == 0f) {
            diameter = (3 * ScreenUtils.getAppScreenWidth() / 5).toFloat()
        }
        bgRect = RectF()
        bgRect?.apply {
            top = longdegree + progressWidth / 2 + DEGREE_PROGRESS_DISTANCE
            left = longdegree + progressWidth / 2 + DEGREE_PROGRESS_DISTANCE
            right = diameter + (longdegree + progressWidth / 2 + DEGREE_PROGRESS_DISTANCE)
            bottom = diameter + (longdegree + progressWidth / 2 + DEGREE_PROGRESS_DISTANCE)
        }
        //圆心
        centerX = (2 * longdegree + progressWidth + diameter + 2 * DEGREE_PROGRESS_DISTANCE) / 2
        centerY = (2 * longdegree + progressWidth + diameter + 2 * DEGREE_PROGRESS_DISTANCE) / 2

        //外部刻度线
        degreePaint = Paint()
        degreePaint.color = Color.parseColor(longDegreeColor)


        linePaint = Paint()
        linePaint.color = Color.parseColor("#ffffff")

        //整个弧形
        allArcPaint = Paint()
        allArcPaint.isAntiAlias = true
        allArcPaint.style = Paint.Style.STROKE
        allArcPaint.strokeWidth = bgArcWidth
        allArcPaint.color = Color.parseColor(bgArcColor)
        allArcPaint.strokeCap = Paint.Cap.ROUND

        //当前进度的弧形
        progressPaint = Paint()
        progressPaint.isAntiAlias = true
        progressPaint.style = Paint.Style.STROKE
        progressPaint.strokeCap = Paint.Cap.ROUND
        progressPaint.strokeWidth = bgArcWidth
        progressPaint.color = Color.WHITE
        val lg = LinearGradient(
            centerX - diameter / 2,
            centerY,
            centerX + diameter / 2,
            centerY - diameter / 2,
            Color.parseColor("#ffffff"),
            Color.parseColor("#ffffff"),
            Shader.TileMode.MIRROR
        )
        progressPaint.shader = lg
        //内容显示文字
        vTextPaint = Paint()
        vTextPaint.textSize = textSize
        vTextPaint.color = Color.parseColor(contentColor)
        vTextPaint.textAlign = Paint.Align.CENTER

        //显示单位文字
        hintPaint = Paint()
        hintPaint.textSize = hintSize
        hintPaint.color = Color.parseColor(hintColor)
        hintPaint.textAlign = Paint.Align.CENTER

        //画进度调最后的小圆点
        dotPaint = Paint()
        dotPaint.isAntiAlias = true
        dotPaint.style = Paint.Style.STROKE
        dotPaint.color = dotColor
        dotPaint.strokeWidth = dotWidth
        dotPaint.strokeCap = Paint.Cap.ROUND

        //显示标题文字
        curSpeedPaint = Paint()
        curSpeedPaint.textSize = curSpeedSize
        curSpeedPaint.color = Color.parseColor(hintColor)
        curSpeedPaint.textAlign = Paint.Align.CENTER

        mDrawFilter = PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG or Paint.FILTER_BITMAP_FLAG)
        sweepGradient = SweepGradient(centerX, centerY, colors, null)
        rotateMatrix = Matrix()

    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        val width =
            (2 * longdegree + progressWidth + diameter + 2 * DEGREE_PROGRESS_DISTANCE).toInt()
        val height =
            (2 * longdegree + progressWidth + diameter * sweepAngle / 360 + 2 * DEGREE_PROGRESS_DISTANCE).toInt()
        setMeasuredDimension(width, height + dipToPx(60f))
    }

    override fun onDraw(canvas: Canvas?) {
        //抗锯齿
        startAngle = 270 - sweepAngle / 2f
        canvas?.apply {
            drawFilter = mDrawFilter
            if (isNeedDial) {
                //画刻度线
                drawDial(this)
            }
            //整个弧
            drawArc(bgRect!!, startAngle, sweepAngle, false, allArcPaint)
            //设置渐变色
            rotateMatrix!!.setRotate(130f, centerX, centerY)
            sweepGradient!!.setLocalMatrix(rotateMatrix)

            //当前进度
            drawArc(bgRect!!, startAngle, currentAngle, false, progressPaint)

            if (isNeedEndDot) {
                // 计算转过的角度
                drawArc(bgRect!!, currentAngle + startAngle - 0.5f, 0.5f, false, dotPaint)
            }

            if (isNeedContent) {
                drawText(
                    String.format("%.0f", curValues),
                    centerX,
                    centerY + textSize / 3,
                    vTextPaint
                )
            }
            if (isNeedUnit) {
                drawText(hintString!!, centerX, centerY + 2 * textSize / 3, hintPaint)
            }
            if (isNeedTitle) {
                drawText(titleString!!, centerX, centerY - 2 * textSize / 3, curSpeedPaint)
            }
            invalidate()
        }
    }

    private fun drawDial(canvas: Canvas) {
        degreePaint.strokeCap = Paint.Cap.ROUND
        for (i in 0..17) {
            if (i in 8..10) {
                canvas.rotate(20f, centerX, centerY)
                continue
            }
            degreePaint.strokeWidth = dipToPx(3.0f).toFloat()
            degreePaint.color = Color.parseColor(shortDegreeColor)
            canvas.drawLine(
                centerX,
                centerY - diameter / 2 + progressWidth / 2 + DEGREE_PROGRESS_DISTANCE,
                centerX,
                centerY - diameter / 2 + progressWidth / 2 + DEGREE_PROGRESS_DISTANCE + shortdegree,
                degreePaint
            )
            canvas.rotate(20f, centerX, centerY)
        }
    }

    /**
     * 设置最大值
     *
     * @param maxValues
     */
    fun setMaxValues(maxValues: Float) {
        this.maxValues = maxValues
        k = sweepAngle / maxValues
    }

    /**
     * 设置当前值
     */
    fun setCurrentValues(value: Float) {
        var currentValues = value
        if (currentValues > maxValues) {
            currentValues = maxValues
        }
        if (currentValues < 0) {
            currentValues = 0f
        }
        curValues = currentValues
        lastAngle = currentAngle
        setAnimation(lastAngle, currentValues * k)
    }


    private lateinit var progressAnimator: ValueAnimator
    private fun setAnimation(last: Float, current: Float) {
        progressAnimator = ValueAnimator.ofFloat(last, current)
        progressAnimator.duration = aniSpeed.toLong()
        progressAnimator.setTarget(currentAngle)
        progressAnimator.addUpdateListener { animation ->
            currentAngle = animation.animatedValue as Float
            curValues = currentAngle / k
        }
        progressAnimator.start()
    }

    private fun dipToPx(dip: Float): Int {
        val density = context.resources.displayMetrics.density;
        return (dip * density + 0.5f).toInt()
    }
}